package com.lc.ibps.platform.rest.bpmn;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.lc.ibps.api.base.model.PartyEntity;
import com.lc.ibps.api.base.model.User;
import com.lc.ibps.api.base.query.Direction;
import com.lc.ibps.api.base.query.FieldSort;
import com.lc.ibps.api.base.query.QueryFilter;
import com.lc.ibps.api.base.query.QueryOP;
import com.lc.ibps.api.bo.model.IDataObject;
import com.lc.ibps.api.form.constants.RightsScope;
import com.lc.ibps.api.form.service.IFormRightsService;
import com.lc.ibps.api.form.vo.FormPermissionVo;
import com.lc.ibps.api.org.service.IPartyEntityService;
import com.lc.ibps.base.bo.constants.DataSaveMode;
import com.lc.ibps.base.core.entity.ResultMessage;
import com.lc.ibps.base.core.util.AppUtil;
import com.lc.ibps.base.core.util.BeanUtils;
import com.lc.ibps.base.core.util.JacksonUtil;
import com.lc.ibps.base.core.util.json.JsonUtil;
import com.lc.ibps.base.core.util.string.StringUtil;
import com.lc.ibps.base.db.id.UniqueIdUtil;
import com.lc.ibps.base.db.model.DefaultQueryFilter;
import com.lc.ibps.base.db.mybatis.domain.DefaultFieldSort;
import com.lc.ibps.base.framework.helper.MapBuilder;
import com.lc.ibps.base.framework.page.PageList;
import com.lc.ibps.base.framework.page.PageResult;
import com.lc.ibps.base.web.context.ContextUtil;
import com.lc.ibps.base.web.util.RequestUtil;
import com.lc.ibps.bpmn.api.cmd.ActionCmd;
import com.lc.ibps.bpmn.api.constant.ActionType;
import com.lc.ibps.bpmn.api.constant.BpmConstants;
import com.lc.ibps.bpmn.api.constant.NodeType;
import com.lc.ibps.bpmn.api.constant.PrivilegeMode;
import com.lc.ibps.bpmn.api.context.BpmnContextUtil;
import com.lc.ibps.bpmn.api.define.IBpmDefineReader;
import com.lc.ibps.bpmn.api.model.define.BpmDefineAttributes;
import com.lc.ibps.bpmn.api.model.define.IBpmDefine;
import com.lc.ibps.bpmn.api.model.define.IBpmProcDefine;
import com.lc.ibps.bpmn.api.model.define.IBpmProcExtendDefine;
import com.lc.ibps.bpmn.api.model.define.IBpmVariableDefine;
import com.lc.ibps.bpmn.api.model.define.NodeAttributes;
import com.lc.ibps.bpmn.api.model.form.FormCategory;
import com.lc.ibps.bpmn.api.model.form.IFormModel;
import com.lc.ibps.bpmn.api.model.identity.BpmIdentity;
import com.lc.ibps.bpmn.api.model.inst.IBpmProcInst;
import com.lc.ibps.bpmn.api.model.node.Button;
import com.lc.ibps.bpmn.api.model.node.IBpmNodeDefine;
import com.lc.ibps.bpmn.api.model.node.ProcBoDefine;
import com.lc.ibps.bpmn.api.model.node.SignNodeDefine;
import com.lc.ibps.bpmn.api.model.task.IBpmTask;
import com.lc.ibps.bpmn.api.model.task.IBpmTaskApproval;
import com.lc.ibps.bpmn.api.nat.task.NatTaskService;
import com.lc.ibps.bpmn.api.service.BpmApprovalService;
import com.lc.ibps.bpmn.api.service.BpmBoService;
import com.lc.ibps.bpmn.api.service.BpmDefineService;
import com.lc.ibps.bpmn.api.service.BpmFormService;
import com.lc.ibps.bpmn.api.service.BpmProcInstService;
import com.lc.ibps.bpmn.api.service.BpmTaskActionService;
import com.lc.ibps.bpmn.api.service.BpmTaskManagerService;
import com.lc.ibps.bpmn.api.service.BpmTaskService;
import com.lc.ibps.bpmn.api.service.SignService;
import com.lc.ibps.bpmn.cmd.IbpsProcInstCmd;
import com.lc.ibps.bpmn.cmd.IbpsTaskFinishCmd;
import com.lc.ibps.bpmn.core.model.var.BpmVariableDefine;
import com.lc.ibps.bpmn.model.define.BpmProcExtendDefine;
import com.lc.ibps.bpmn.persistence.entity.BpmApprovePo;
import com.lc.ibps.bpmn.persistence.entity.BpmDefinePo;
import com.lc.ibps.bpmn.persistence.entity.BpmInstPo;
import com.lc.ibps.bpmn.persistence.entity.BpmTaskChangePo;
import com.lc.ibps.bpmn.persistence.entity.BpmTaskPo;
import com.lc.ibps.bpmn.repository.BpmDefineRepository;
import com.lc.ibps.bpmn.repository.BpmInstRepository;
import com.lc.ibps.bpmn.repository.BpmTaskChangeRepository;
import com.lc.ibps.bpmn.repository.BpmTaskRepository;
import com.lc.ibps.bpmn.utils.BpmButtonUtil;
import com.lc.ibps.bpmn.utils.BpmExecUtil;
import com.lc.ibps.bpmn.utils.BpmIdentityUtil;
import com.lc.ibps.bpmn.utils.PartyUtil;
import com.lc.ibps.cloud.entity.APIPageList;
import com.lc.ibps.cloud.entity.APIRequest;
import com.lc.ibps.cloud.entity.APIResult;
import com.lc.ibps.org.party.persistence.entity.PartyEntityPo;
import com.lc.ibps.web.controller.BaseApiController;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

/**
 * 流程接口。
 *
 * <pre>
 *  
 * 构建组：ibps-platform-admin
 * 作者：hugh zhuang
 * 邮箱：3378340995@qq.com
 * 日期：2016年11月30日-下午4:03:46
 * 版权：广州流辰信息技术有限公司版权所有
 * </pre>
 */
@RequestMapping(value = "/api/webapi/bpmService")
@Api(value = "/bpmService",tags="流程管理-流程任务服务" )
@RestController
public class BpmActController extends BaseApiController {

	private BpmTaskManagerService bpmTaskManagerService;
	private BpmApprovalService bpmApproveService;
	private IPartyEntityService entityService;
	private IFormRightsService formRightsService;
	private BpmFormService bpmFormService;
	private BpmBoService bpmBoService;
	private BpmTaskService bpmTaskService;
	private BpmTaskRepository bpmTaskRepository;
	private BpmTaskChangeRepository bpmTaskChangeRepository;
	private BpmProcInstService bpmInstService;
	private BpmInstRepository bpmInstRepository;
	private BpmTaskActionService bpmTaskActionService;
	private BpmDefineService bpmDefineService;
	private IBpmDefineReader bpmDefineReader;
	private BpmProcInstService bpmProcInstService;
	private NatTaskService natTaskService;
	private SignService signService;
	private BpmApprovalService bpmApprovalService;
	private BpmDefineRepository bpmDefineRepository;

	public BpmActController() {
		bpmTaskManagerService = AppUtil.getBean(BpmTaskManagerService.class);
		bpmApproveService = AppUtil.getBean(BpmApprovalService.class);
		entityService = AppUtil.getBean(IPartyEntityService.class);
		formRightsService = AppUtil.getBean(IFormRightsService.class);
		bpmFormService = AppUtil.getBean(BpmFormService.class);
		bpmBoService = AppUtil.getBean(BpmBoService.class);
		bpmTaskService = AppUtil.getBean(BpmTaskService.class);
		bpmTaskRepository = AppUtil.getBean(BpmTaskRepository.class);
		bpmTaskChangeRepository = AppUtil.getBean(BpmTaskChangeRepository.class);
		bpmInstService = AppUtil.getBean(BpmProcInstService.class);
		bpmInstRepository = AppUtil.getBean(BpmInstRepository.class);
		bpmTaskActionService = AppUtil.getBean(BpmTaskActionService.class);
		bpmDefineService = AppUtil.getBean(BpmDefineService.class);
		bpmDefineReader = AppUtil.getBean(IBpmDefineReader.class);
		bpmProcInstService = AppUtil.getBean(BpmProcInstService.class);
		natTaskService = AppUtil.getBean(NatTaskService.class);
		signService = AppUtil.getBean(SignService.class); 
		bpmApprovalService = AppUtil.getBean(BpmApprovalService.class);
		bpmDefineRepository = AppUtil.getBean(BpmDefineRepository.class);
	}

	@ApiOperation(value = "我的待办事项", notes = "我的待办事项")
	@RequestMapping(value = "/myTasks", method = RequestMethod.POST)
	public APIResult<APIPageList<BpmTaskPo>> myTasks(
			@ApiParam(name = "request", value = "传入查询请求json字符串", required = true) 
			@RequestBody(required = true) APIRequest request) {
		APIResult<APIPageList<BpmTaskPo>> result = new APIResult<>();
		QueryFilter queryFilter = getQuerFilter(request);
		// 流程定义名称
		// String proDefName = this.getVal(interParam, "proDefName");
		// if (StringUtil.isNotEmpty(proDefName)) {
		// pm.put("proDefName", proDefName);
		// }
		try {
			String userId = ContextUtil.getCurrentUserId();
			List<PartyEntity> pes = new ArrayList<PartyEntity>();
			String data = entityService.findByUserIdJson(userId);
			if (JacksonUtil.isJsonArray(data)) {
				List<PartyEntityPo> peps = JacksonUtil.getDTOList(data, PartyEntityPo.class);
				pes.addAll(peps);
			}
			Map<String, String> groups = PartyUtil.convertGroupList(pes, userId); // 构建组 groups
			// 查询列表
			List<BpmTaskPo> list = bpmTaskRepository.queryByUser(userId, groups, queryFilter);
			
			APIPageList<BpmTaskPo> pageList = getAPIPageList(list);
			result.setData(pageList);
			result.setMessage("获取待办事项成功");
		} catch (Exception e) {
			result = getExceptionResult(result, ERROR, "获取待办事项失败", e);
		}
		return result;
	}
	
	@ApiOperation(value = "首页的数量", notes = "首页的数量")
	@RequestMapping(value = "/getInfoCount", method = RequestMethod.GET)
	public APIResult<Map<String, Object>>getInfoCount(){
		APIResult<Map<String, Object>> result = new APIResult<Map<String, Object>>();
		MapBuilder map = b();
		DefaultQueryFilter queryFilter =  new DefaultQueryFilter();
		queryFilter.setPage(null);
		String userId = ContextUtil.getCurrentUserId();
		try {
			//========== 待办事宜
			List<PartyEntity> pes = new ArrayList<PartyEntity>();
			String data = entityService.findByUserIdJson(userId);
			if (JacksonUtil.isJsonArray(data)) {
				List<PartyEntityPo> peps = JacksonUtil.getDTOList(data, PartyEntityPo.class);
				pes.addAll(peps);
			}
			Map<String, String> groups = PartyUtil.convertGroupList(pes, userId); // 构建组 groups
		
			
			List<BpmTaskPo> list1 = bpmTaskRepository.queryByUser(userId, groups, queryFilter);
			map.a("pending", list1.size());
		} catch (Exception e) {
			//		result = getExceptionResult(result, ERROR, "获取首页数量失败", e);
		}		
		try {
			//========== 已办事宜
			List<?> list2 = bpmInstRepository.queryHandled(userId, queryFilter);
			map.a("handled", list2.size());
		} catch (Exception e) {
			//		result = getExceptionResult(result, ERROR, "获取首页数量失败", e);
		}		
		try {
			//========== 办结事宜
			List<?> list3 = bpmInstRepository.queryCompleted(userId, queryFilter);
			map.a("completed", list3.size());
		} catch (Exception e) {
			//		result = getExceptionResult(result, ERROR, "获取首页数量失败", e);
		}		
		try {
				//========== 我的请求
				List<?> list4 = bpmInstRepository.queryRequest(userId, queryFilter);
				map.a("myRequest", list4.size());
		} catch (Exception e) {
			//		result = getExceptionResult(result, ERROR, "获取首页数量失败", e);
		}		
		try {
			//========== 新建流程
			List<?> list5 = bpmDefineRepository.queryDef(userId,ContextUtil.isSuper());
			map.a("newProcess", list5.size());
		} catch (Exception e) {
			//		result = getExceptionResult(result, ERROR, "获取首页数量失败", e);
		}		
		try {
			//========== 我的草稿
			List<?> list6 =  bpmInstRepository.queryDrafts(userId, queryFilter);
			map.a("myDraft", list6.size());
		} catch (Exception e) {
			//		result = getExceptionResult(result, ERROR, "获取首页数量失败", e);
		}		
		try {
			//========== 我的撤销
			List<?> list7 = bpmInstRepository.queryRevoke(userId, queryFilter);
			map.a("myRevoke", list7.size());
		
		} catch (Exception e) {
	//		result = getExceptionResult(result, ERROR, "获取首页数量失败", e);
		}
		try {
			//========== 我的转办代理
			List<?> list8 = bpmTaskChangeRepository.query(queryFilter);
			map.a("taskChange", list8.size());
			
		} catch (Exception e) {
			//		result = getExceptionResult(result, ERROR, "获取首页数量失败", e);
		}
		result.setData(map.p());
		return result;
	}
	/**
	 * 获取任务的详情
	 * 
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@ApiOperation(value = "任务详情页", notes = "任务详情页")
	@RequestMapping(value = "/getFormData", method = RequestMethod.GET)
	public APIResult<Map<String, Object>> getFormData(
			@ApiParam(name = "taskId", value = "任务ID", required = false) @RequestParam(name = "taskId", required = false) String taskId) {

		APIResult<Map<String, Object>> result = new APIResult<>();
		IDataObject dataObject = null;
		IFormModel formModel = null;
		String permissions = "";
		List<Button> buttons = null;
		Map<String, Object> map = Maps.newHashMap();
		try {
			User curUser = ContextUtil.getCurrentUser();
			BpmTaskPo task = bpmTaskRepository.get(taskId);
			if (BeanUtils.isEmpty(task)) {
				result = getResult(result, FAIL, "任务不存在，可能已经被处理了.");
				return result;
			}
			String procInstId = task.getProcInstId();
			String defId = task.getProcDefId();
			String nodeId = task.getNodeId();

			IBpmProcInst bpmProcessInstance = bpmInstService.getProcInst(procInstId);
			//设置标题
			map.put("title", bpmProcessInstance.getProcDefName());
			// 表单
			formModel = bpmFormService.getByDefId(defId, nodeId, bpmProcessInstance);

			// BO数据
			dataObject = bpmBoService.getDataByInst(bpmProcessInstance);

			// BO数据字段权限过滤
			if (BeanUtils.isNotEmpty(formModel) && FormCategory.INNER.equals(formModel.getType())) {

				Map<String, String> rightsMap = new HashMap<String, String>();
				rightsMap.put(FormPermissionVo.FLOW_KEY, bpmProcessInstance.getProcDefKey());
				rightsMap.put(FormPermissionVo.NODE_ID, nodeId);

				permissions = formRightsService.getPermission(new FormPermissionVo(RightsScope.NODE,
						ContextUtil.getCurrentUserId(), formModel.getKey(), rightsMap));
			}

			// 按钮
			IBpmNodeDefine taskNodeDef = bpmDefineReader.getNode(defId, nodeId);
			String partyEntityData = entityService.findByUserAccountJson(curUser.getAccount());
			List<PartyEntity> groups = new ArrayList<PartyEntity>();
			if(JacksonUtil.isJsonArray(partyEntityData)){
				List<PartyEntityPo> pes = JacksonUtil.getDTOList(partyEntityData, PartyEntityPo.class);
				groups.addAll(pes);
			}
			List<String> gids = PartyUtil.partyToGroupId(groups);
			
			buttons = getButton(curUser, dataObject, task, taskNodeDef, gids);

			// 审批意见
			List<IBpmTaskApproval> opinionList = bpmApproveService
					.setAuditorInfo(bpmApproveService.getFormOpinionByInstId(task.getProcInstId()));

			// 按钮
			map.put("buttons", buttons);
			// 表单
			map.put("formModel", formModel);
			// bo数据
			map.put("boData", BeanUtils.isNotEmpty(dataObject) ? dataObject.getData() : null);
			//版本号
			map.put("version",  BeanUtils.isNotEmpty(dataObject) ? dataObject.getVersion() : 0);
			// 表单权限
			map.put("permissions", permissions);

			// 是否隐藏意见框
			// 子流程节点设置应该另外考虑
			boolean isHideOpinion = false;
			boolean isHidePath = false;
			boolean isCommonJumpType = false;
			boolean isEnd = false;
			if (taskNodeDef != null) {
				NodeAttributes nodeAttributes = taskNodeDef.getLocalProperties();
				isHideOpinion = BeanUtils.isNotEmpty(nodeAttributes) ? nodeAttributes.isHideOpinion() : isHideOpinion;
				isHidePath = BeanUtils.isNotEmpty(nodeAttributes) ? nodeAttributes.isHidePath() : isHidePath;
				isCommonJumpType = BeanUtils.isNotEmpty(nodeAttributes) ? nodeAttributes.getJumpType().equals("common")
						: isCommonJumpType;

				List<IBpmNodeDefine> outcomeNodes = taskNodeDef.getOutgoingNodeList();
				List<IBpmNodeDefine> handlerSelectOutcomeNodes = handlerSelectOutgoingNodes(outcomeNodes);
				List<IBpmNodeDefine> pathOutgoingNodes = Lists.newArrayList(handlerSelectOutcomeNodes);
				List<IBpmNodeDefine> removeList = new ArrayList<IBpmNodeDefine>();
				for (IBpmNodeDefine bpmNodeDef : pathOutgoingNodes) {
					if (NodeType.END.equals(bpmNodeDef.getType())) {
						removeList.add(bpmNodeDef);
					}
				}
				pathOutgoingNodes.removeAll(removeList);
				if (BeanUtils.isEmpty(pathOutgoingNodes)) {
					isEnd = true;
				}
			}
			String lockUser = bpmTaskRepository.isLock(taskId);

			String suspendState = "0";
			if (BeanUtils.isNotEmpty(task)) {
				suspendState = String.valueOf(task.getSuspendState());
			}

			Map<String, Object> attributes = Maps.newHashMap();
			attributes.put("lockUser", lockUser);
			attributes.put("suspendState", suspendState);
			attributes.put("curUserId", ContextUtil.getCurrentUserId());
			attributes.put("opinionList", opinionList);
			attributes.put("isHideOpinion", isHideOpinion);
			attributes.put("isHidePath", isHidePath);
			attributes.put("isCommonJumpType", isCommonJumpType);
			attributes.put("isEnd", isEnd);
			map.put("attributes", attributes);

			result.setData(map);
			result.setMessage("成功获取任务！");
		} catch (Exception e) {
			result = getExceptionResult(result, ERROR, "获取任务失败", e);
		}

		return result;
	}
	
	private List<Button> getButton(User curUser, IDataObject dataObject, BpmTaskPo task,
			IBpmNodeDefine taskNodeDef, List<String> gids) {
		List<Button> buttons;
		if(BeanUtils.isEmpty(task)){
			buttons = BpmButtonUtil.getButtons(taskNodeDef, task, dataObject, curUser.getUserId(), gids);
			return buttons;
		}
		Map<String, Object> params = new HashMap<String, Object>();
		// 流程配置是否允许转办
		IBpmDefineReader reader = AppUtil.getBean(IBpmDefineReader.class);
		IBpmProcDefine<IBpmProcExtendDefine> procDefine = reader.getBpmProcDefine(task.getProcDefId());
		BpmDefineAttributes attributes = procDefine.getBpmProcExtendDefine().getExtendAttributes();
		boolean allow = attributes.isAllowTransTo();
		if(allow){
			// 是否存在运行中的任务变更记录
			List<BpmTaskChangePo> chgList = bpmTaskChangeRepository.findByTask(task.getId(), BpmTaskChangePo.CHANGE_STATUS_RUNNING);
			if(BeanUtils.isEmpty(chgList)){
				params.put("isHiddenDelegate", false);
			}else{
				params.put("isHiddenDelegate", true);
			}
		}else{
			params.put("isHiddenDelegate", true);
		}
		params.put("userId", curUser.getUserId());
		params.put("isSuper", curUser.isSuper());
		params.put("suspendState", task.getSuspendState());
		if(StringUtil.isNotEmpty(task.getLockUser())){
			params.put("lockUser", task.getLockUser());
		}
		buttons = BpmButtonUtil.filterButtons(
				BpmButtonUtil.getButtons(taskNodeDef, task, dataObject, curUser.getUserId(), gids), params);
		return buttons;
	}

	@RequestMapping(value = "/myHandled", method = RequestMethod.POST)
	@ApiOperation(value = "我的已办事项", notes = "我的已办事项")
	public APIResult<APIPageList<BpmInstPo>> myHandled(
			@ApiParam(name = "request", value = "传入查询请求json字符串", required = true) @RequestBody(required = true) APIRequest request) {

		APIResult<APIPageList<BpmInstPo>> result = new APIResult<>();
		QueryFilter queryFilter = getQuerFilter(request);
		// 查询列表
		try {
			String userId = ContextUtil.getCurrentUserId();
			List<BpmInstPo> listData = null;
			// 是否是办结菜单
			if (StringUtil.isNotEmpty(request.getParameter("end"))) {
				listData = bpmInstRepository.queryEndHandled(userId, queryFilter);
			} else {
				listData = bpmInstRepository.queryHandled(userId, queryFilter);
			}
			APIPageList<BpmInstPo> pageList = getAPIPageList(listData);
			result.setData(pageList);
			result.setMessage("获取已办事项成功");
		} catch (Exception e) {
			result = getExceptionResult(result, ERROR, "获取已办事项失败", e);
		}

		return result;
	}

	@ApiOperation(value = "我的办结事项", notes = "我的办结事项")
	@RequestMapping(value = "/myCompleted", method = RequestMethod.POST)
	public APIResult<APIPageList<BpmInstPo>> myCompleted(
			@ApiParam(name = "request", value = "传入查询请求json字符串", required = true) @RequestBody(required = true) APIRequest request) {

		APIResult<APIPageList<BpmInstPo>> result = new APIResult<>();
		QueryFilter queryFilter = getQuerFilter(request);
		// 查询列表
		try {
			String userId = ContextUtil.getCurrentUserId();
			List<BpmInstPo> listData = bpmInstRepository.queryCompleted(userId, queryFilter);
			APIPageList<BpmInstPo> pageList = getAPIPageList(listData);
			result.setData(pageList);
			result.setMessage("获取办结事项成功");
		} catch (Exception e) {
			result = getExceptionResult(result, ERROR, "获取办结事项失败", e);
		}

		return result;
	}

	@ApiOperation(value = "我的请求", notes = "我的请求")
	@RequestMapping(value = "/myRequest", method = RequestMethod.POST)
	public APIResult<APIPageList<BpmInstPo>> myRequest(
			@ApiParam(name = "request", value = "传入查询请求json字符串", required = true) @RequestBody(required = true) APIRequest request) {

		APIResult<APIPageList<BpmInstPo>> result = new APIResult<>();
		QueryFilter queryFilter = getQuerFilter(request);
		// 查询列表
		try {
			String userId = ContextUtil.getCurrentUserId();
			List<BpmInstPo> listData = bpmInstRepository.queryRequest(userId, queryFilter);
			APIPageList<BpmInstPo> pageList = getAPIPageList(listData);
			result.setData(pageList);
			result.setMessage("获取我的请求成功");
		} catch (Exception e) {
			result = getExceptionResult(result, ERROR,"获取我的请求失败", e);
		}

		return result;
	}

	@ApiOperation(value = "我的草稿", notes = "我的草稿")
	@RequestMapping(value = "/myDrafts", method = RequestMethod.POST)
	public APIResult<APIPageList<BpmInstPo>> myDrafts(
			@ApiParam(name = "request", value = "传入查询请求json字符串", required = true) @RequestBody(required = true) APIRequest request) {

		APIResult<APIPageList<BpmInstPo>> result = new APIResult<>();
		QueryFilter queryFilter = getQuerFilter(request);
		// 查询列表
		try {
			String userId = ContextUtil.getCurrentUserId();
			List<BpmInstPo> listData = bpmInstRepository.queryDrafts(userId, queryFilter);
			APIPageList<BpmInstPo> pageList = getAPIPageList(listData);
			result.setData(pageList);
			result.setMessage("获取我的草稿成功");
		} catch (Exception e) {
			result = getExceptionResult(result, ERROR,"获取我的草稿失败", e);
		}

		return result;
	}
	
	@ApiOperation(value = "我的可撤销事务", notes = "我的可撤销事务")
	@RequestMapping(value = "/myRevoke", method = RequestMethod.POST)
	public APIResult<APIPageList<BpmInstPo>> myRevoke(
			@ApiParam(name = "request", value = "传入查询请求json字符串", required = true) @RequestBody(required = true) APIRequest request) {
		
		APIResult<APIPageList<BpmInstPo>> result = new APIResult<>();
		QueryFilter queryFilter = getQuerFilter(request);
		// 查询列表
		try {
			String userId = ContextUtil.getCurrentUserId();
			List<BpmInstPo> listData = bpmInstRepository.queryRevoke(userId, queryFilter);
			APIPageList<BpmInstPo> pageList = getAPIPageList(listData);
			result.setData(pageList);
			result.setMessage("获取我的可撤销事务成功");
		} catch (Exception e) {
			result = getExceptionResult(result, ERROR,"获取我的可撤销事务失败", e);
		}
		
		return result;
	}

	@ApiOperation(value = "启动流程", notes = "启动流程")
	@RequestMapping(value = "/start", method = RequestMethod.POST)
	public APIResult<String> start(
			@ApiParam(name = "bpmnDefId", value = "流程ID", required = true) @RequestParam(name = "bpmnDefId", required = true) String bpmnDefId,
			@ApiParam(name = "destination", value = "目标节点", required = false) @RequestParam(name = "destination", required = false) String destination,
			@ApiParam(name = "fstNodeUsers", value = "发起人", required = false) @RequestParam(name = "fstNodeUsers", required = false) String fstNodeUsers,
			@ApiParam(name = "secNodeUsers", value = "指定跳过第一个节点后第二节点执行人", required = false) @RequestParam(name = "secNodeUsers", required = false) String secNodeUsers,
			@ApiParam(name = "data", value = "流程表单数据", required = true) @RequestParam(name = "data", required = true) String data,
			@ApiParam(name = "proInstId", value = "流程实例id", required = false) @RequestParam(name = "proInstId", required = false) String proInstId,
			@ApiParam(name = "procVars", value = "动态流程变量", required = false) @RequestParam(name = "procVars", required = false) String procVars) {
		APIResult<String> result = new APIResult<>();
		try {
			IbpsProcInstCmd cmd = getStartCmd(bpmnDefId, destination, fstNodeUsers, secNodeUsers, data, proInstId,
					procVars);
			IBpmProcInst bpm = bpmProcInstService.startProcInst(cmd);
			result.setData(bpm.getId());
			result.setMessage("流程启动成功!");
		} catch (Exception e) {
			result = getExceptionResult(result, ERROR, "流程启动失败!", e);
		}
		return result;
	}

	@ApiOperation(value = "保存草稿", notes = "保存草稿")
	@RequestMapping(value = "/saveDraft", method = RequestMethod.POST)
	public APIResult<String> saveDraft(
			@RequestParam(name = "bpmnDefId", required = true) @ApiParam(name = "bpmnDefId", value = "流程ID", required = true) String bpmnDefId,
			@RequestParam(name = "destination", required = false) @ApiParam(name = "destination", value = "目标节点", required = false) String destination,
			@RequestParam(name = "nodeUsers", required = false) @ApiParam(name = "nodeUsers", value = "发起人", required = false) String fstNodeUsers,
			@RequestParam(name = "secNodeUsers", required = false) @ApiParam(name = "secNodeUsers", value = "指定跳过第一个节点后第二节点执行人", required = false) String secNodeUsers,
			@RequestParam(name = "data", required = true) @ApiParam(name = "data", value = "流程表单数据", required = true) String data,
			@RequestParam(name = "proInstId", required = false) @ApiParam(name = "proInstId", value = "流程实例id", required = false) String proInstId,
			@RequestParam(name = "procVars", required = false) @ApiParam(name = "procVars", value = "动态流程变量", required = false) String procVars) {
		APIResult<String> result = new APIResult<>();
		try {
			IbpsProcInstCmd cmd = getStartCmd(bpmnDefId, destination, fstNodeUsers, secNodeUsers, data, proInstId,
					procVars);
			IBpmProcInst bpm = bpmProcInstService.saveDraft(cmd);
			result.setData(bpm.getId());
			result.setMessage("保存草稿成功!");
		} catch (Exception e) {
			result = getExceptionResult(result, ERROR, "保存草稿失败!", e);
		}
		return result;
	}

	@ApiOperation(value = "处理任务", notes = "处理任务")
	@RequestMapping(value = "/complete", method = RequestMethod.POST)
	public APIResult<String> complete(
			@RequestParam(name = "taskId", required = true) @ApiParam(name = "taskId", value = "任务ID", required = true) String taskId,
			@RequestParam(name = "actionName", required = true) @ApiParam(name = "actionName", value = "工作名称", required = true) String actionName,
			@RequestParam(name = "opinion", required = false) @ApiParam(name = "opinion", value = "审批意见", required = false) String opinion,
			@RequestParam(name = "data", required = false) @ApiParam(name = "data", value = "流程表单数据", required = false) String data,
			@RequestParam(name = "nodeUsers", required = false) @ApiParam(name = "nodeUsers", value = "节点执行人", required = false) String nodeUsers,
			@RequestParam(name = "directHandlerSign", required = false) @ApiParam(name = "directHandlerSign", value = "是否会签", required = false) String directHandlerSign,
			@RequestParam(name = "backHandMode", required = false) @ApiParam(name = "backHandMode", value = "驳回模式", required = false) String backHandMode,
			@RequestParam(name = "destination", required = false) @ApiParam(name = "destination", value = "驳回节点", required = false) String destination,
			@RequestParam(name = "procVars", required = false) @ApiParam(name = "procVars", value = "流程动态变量", required = false) String procVars) {

		APIResult<String> returnResult = new APIResult<>();
		try {
			IbpsTaskFinishCmd cmd = getCmdFromRequest(taskId, actionName, opinion, data, nodeUsers, directHandlerSign,
					backHandMode, destination, ContextUtil.getCurrentUserId(), ContextUtil.getCurrentUserFullName(), procVars);
			boolean result = bpmTaskActionService.finishTask(cmd);
			if (result) {
				ActionCmd finsActionCmd = BpmnContextUtil.getActionCmd(cmd.getInstId());
				Object rejectAfterExecutionId = finsActionCmd.getTransitVars("rejectAfterExecutionId");
				if (rejectAfterExecutionId != null && StringUtil.isNotEmpty(rejectAfterExecutionId.toString())) {
					// 调整Activiti的执行表数据
					BpmExecUtil.multipleInstancesRejectAdjust(rejectAfterExecutionId.toString());
				}
			}
			if (result) {
				returnResult.setMessage("操作执行成功！");
			} else {
				returnResult = getResult(returnResult, FAIL, "操作执行失败，请稍后再试");
			}
		} catch (Exception e) {
			returnResult = getExceptionResult(returnResult, ERROR, "操作执行失败", e);
		}
		return returnResult;
	}

	@ApiOperation(value = "终止流程", notes = "终止流程")
	@RequestMapping(value = "/stopProcess", method = RequestMethod.POST)
	public APIResult<String> doEndProcess(
			@RequestParam(name = "taskId", required = true) @ApiParam(name = "taskId", value = "任务ID", required = true) String taskId,
			@RequestParam(name = "messageType", required = false) @ApiParam(name = "messageType", value = "信息类型", required = false) String messageType,
			@RequestParam(name = "endReason", required = false) @ApiParam(name = "endReason", value = "原因", required = false) String endReason)
			throws Exception {
		APIResult<String> result = new APIResult<>();
		try {
			bpmTaskManagerService.endProcessByTaskIds(taskId, messageType, endReason, ContextUtil.getCurrentUserId());
			result.setMessage("终止流程成功");
		} catch (Exception e) {
			result = getExceptionResult(result, ERROR, "终止流程失败", e);
		}
		return result;
	}

	@ApiOperation(value = "获取流程表单", notes = "获取流程表单")
	@RequestMapping(value = "/getInstForm", method = RequestMethod.GET)
	public  APIResult<Map<String, Object>> getInstForm(
			@RequestParam(name = "bpmInstId", required = true) @ApiParam(name = "bpmInstId", value = "流程实例ID", required = true) String bpmInstId) {
		 APIResult<Map<String, Object>> result = new  APIResult<>();
		try {
			if (BeanUtils.isEmpty(bpmInstId)) {
				result = getResult(result, FAIL, "参数错误！");
			}
			Map<String, Object> data = bpmFormService.instFormInfoByInstId(bpmInstId, ContextUtil.getCurrentUserId());
			result.setMessage("成功获取数据！");
			result.setData(data);
		} catch (Exception e) {
			result = getExceptionResult(result, ERROR, "获取表单数据失败", e);
		}
		return result;
	}

	@ApiOperation(value = "获取审批历史", notes = "获取审批历史")
	@RequestMapping(value = "/opinions", method = RequestMethod.GET)
	public APIResult<APIPageList<IBpmTaskApproval>> opinions(
			@ApiParam(name = "bpmInstId", value = "流程实例ID", required = false) @RequestParam(name = "bpmInstId", required = false) String bpmInstId,
			@ApiParam(name = "taskId", value = "任务Id", required = false) @RequestParam(name = "taskId", required = false) String taskId) {
		APIResult<APIPageList<IBpmTaskApproval>> result = new APIResult<>();
		try {
			if (BeanUtils.isNotEmpty(taskId)) {
				IBpmTask task = bpmTaskService.getByTaskId(taskId);
				bpmInstId = task.getProcInstId();
			}

			List<IBpmTaskApproval> opinionList = bpmApproveService.setAuditorInfo(
					bpmApproveService.findApprovalHisIgnoreFirstSkip(bpmInstId, ContextUtil.getCurrentUserId()));
			APIPageList<IBpmTaskApproval> pageList = getAPIPageList(opinionList);
			result.setData(pageList);
			result.setMessage("成功获取数据!");
		} catch (Exception e) {
			result = getExceptionResult(result, ERROR, "获取数据失败", e);
		}
		return result;
	}

	@ApiOperation(value = "获取操作相关信息", notes = "获取操作相关信息")
	@RequestMapping(value = "/actionMessage", method = RequestMethod.POST)
	public APIResult<Map<String, Object>> actionMessage(
			@RequestParam(name = "taskId", required = true) @ApiParam(name = "taskId", value = "任务Id", required = true) String taskId,
			@RequestParam(name = "actionName", required = true) @ApiParam(name = "actionName", value = "动作", required = true) String actionName) {
		APIResult<Map<String, Object>> result = new APIResult<>();
		Map<String, Object> map = new HashMap<String, Object>();
		try {
			BpmTaskPo task = (BpmTaskPo) bpmTaskService.getByTaskId(taskId);
			IBpmProcInst bpmProcessInstance = bpmInstService.getProcInst(task.getProcInstId());
			String defId = task.getProcDefId();
			String nodeId = task.getNodeId();
			IBpmNodeDefine taskNodeDef = bpmDefineReader.getNode(defId, nodeId);
			// 非弃权动作并且是会签任务
			if (!"abandon".equals(actionName) && taskNodeDef.getType().equals(NodeType.SIGNTASK)) {
				notAbandon(task, bpmProcessInstance, map, taskNodeDef, ContextUtil.getCurrentUserAccount());
			}
			// result.setData("true");
			result.setMessage("成功获取数据!");

		} catch (Exception e) {
			result = getExceptionResult(result, ERROR, "获取数据失败", e);
		}
		return result;
	}

	/**
	 * 非弃权动作并且是会签任务
	 *
	 * @param task
	 * @param bpmProcessInstance
	 * @param autoView
	 * @param taskNodeDef
	 */
	private void notAbandon(BpmTaskPo task, IBpmProcInst bpmProcessInstance, Map<String, Object> result,
			IBpmNodeDefine taskNodeDef, String account) {
		IDataObject dataObjects = bpmBoService.getDataByInst(bpmProcessInstance);
		Map<String, Object> variables = natTaskService.getVariables(task.getTaskId());
		String partyEntityData = entityService.findByUserAccountJson(account);
		List<PartyEntity> groups = new ArrayList<PartyEntity>();
		if(JacksonUtil.isJsonArray(partyEntityData)){
			List<PartyEntityPo> pes = JacksonUtil.getDTOList(partyEntityData, PartyEntityPo.class);
			groups.addAll(pes);
		}
		List<String> gids = PartyUtil.partyToGroupId(groups);
		List<PrivilegeMode> privilege = signService.getPrivilege(ContextUtil.getCurrentUserId(), gids,
				(SignNodeDefine) taskNodeDef, variables, dataObjects);
		// 拥有直接处理会签任务的特权
		if (privilege.contains(PrivilegeMode.ALL) || privilege.contains(PrivilegeMode.DIRECT)) {
			result.put("directHandlerSign", true);
		}
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	private IbpsTaskFinishCmd getCmdFromRequest(String taskId, String actionName, String opinion, String busData,
			String nodeUsers, String directHandlerSign, String backHandMode, String destination, String curUser,
			String curUserName, String procVars) {
		String jumpType = "common";
		if (StringUtil.isNotEmpty(nodeUsers)) {
			JSONArray nodeUserArr = JSONArray.fromObject(nodeUsers);
			if (JsonUtil.isNotEmpty(nodeUserArr)) {
				jumpType = JsonUtil.getString(nodeUserArr.getJSONObject(0), "jumpType");
				destination = JsonUtil.getString(nodeUserArr.getJSONObject(0), "nodeId");
			}
		}

		IbpsTaskFinishCmd cmd = new IbpsTaskFinishCmd();
		cmd.setCurUser(curUser);
		cmd.setCurUserName(curUserName);
		cmd.addTransitVars(BpmConstants.CUR_USER, curUser);
		cmd.setTaskId(taskId);// 任务ID
		cmd.setActionName(actionName);// 处理动作
		// 指定路径、自由跳转
		if ("select".equals(jumpType) || "free".equals(jumpType)) {
			if (StringUtil.isNotEmpty(destination)) {
				cmd.setDestination(destination);
			}
		}

		// 指定执行人
		if (BeanUtils.isNotEmpty(nodeUsers)) {
			Map<String, List<BpmIdentity>> specUserMap = BpmIdentityUtil.getBpmIdentity(nodeUsers);
			cmd.addTransitVars(BpmConstants.BPM_NODE_USERS, specUserMap);
		}

		// 设置流程驳回时跳转模式
		cmd.addTransitVars(BpmConstants.BACK_HAND_MODE, backHandMode);
		if (ActionType.REJECT.getKey().equals(actionName)) {
			// 驳回到指定节点
			if (StringUtil.isNotEmpty(destination)) {
				cmd.setDestination(destination);
			}
		}

		// 会签任务的直接处理
		if ("true".equals(directHandlerSign)) {
			cmd.addTransitVars(BpmConstants.SIGN_DIRECT, "1");
		}

		// 设置表单意见
		cmd.setApprovalOpinion(opinion);
		handOpinion(busData, cmd);
		IBpmTask task = bpmTaskService.getTaskId(taskId);
		if (StringUtil.isNotEmpty(busData)) {
			IBpmProcDefine<BpmProcExtendDefine> bpmProcessDef = (IBpmProcDefine) bpmDefineReader
					.getBpmProcDefine(task.getProcDefId());
			BpmProcExtendDefine bpmProcExtendDefine = bpmProcessDef.getBpmProcExtendDefine();
			String dataSaveMode = DataSaveMode.TABLE;
			FormCategory formCategory = bpmProcExtendDefine.getGlobalForm().getType();
			if (FormCategory.INNER.equals(formCategory)) {
				ProcBoDefine boDef = bpmProcExtendDefine.getBoDefine();
				dataSaveMode = boDef.isSaveTable() ? DataSaveMode.TABLE : DataSaveMode.INSTANCE;
			} else if (FormCategory.URL_LOAD.equals(formCategory)) {
				dataSaveMode = ActionCmd.DATA_MODE_PAIR;
			} else if (FormCategory.FRAME.equals(formCategory)) {
				dataSaveMode = ActionCmd.DATA_MODE_PK;
			}

			cmd.setDataMode(dataSaveMode);

			cmd.setBusData(busData);
		}

		// 添加变量的设置
		Map<String, Object> vars = this.getTaskVars(taskId);
		// 动态变量设置
		JSONObject procVarsJS = JSONObject.fromObject(StringUtil.isNotEmpty(procVars) ? procVars : "{}");
		Iterator<String> keys = procVarsJS.keys();
		while (keys.hasNext()) {
			String key = keys.next().toString();
			String value = procVarsJS.get(key).toString();
			vars.put(key, value);
		}
		cmd.setVariables(vars);

		IBpmProcInst bpmInst = bpmInstService.getProcInstByBpmnInst(task.getBpmnInstId());
		cmd.setBusinessKey(bpmInst.getBizKey());
		return cmd;
	}

	@SuppressWarnings("unchecked")
	private void handOpinion(String data, IbpsTaskFinishCmd cmd) {
		if (StringUtil.isEmpty(data))
			return;
		String opinion = "";
		JSONObject dataJson = JSONObject.fromObject(data);
		if (!dataJson.containsKey(BpmApprovePo.OPINION_FLAG))
			return;
		JSONObject opinionJson = dataJson.getJSONObject(BpmApprovePo.OPINION_FLAG);
		Iterator<String> keys = opinionJson.keys();
		String opinionName = "";
		while (keys.hasNext()) {
			opinionName = keys.next();
			if (StringUtil.isNotEmpty(opinionJson.getString(opinionName))) {
				cmd.setOpinionIdentity(opinionName);
				opinion = opinionJson.getString(opinionName);
				cmd.setApprovalOpinion(opinion);
				break;
			}
		}
		dataJson.remove(BpmApprovePo.OPINION_FLAG);
		data = dataJson.toString();
		cmd.setBusData(data);
	}

	/**
	 * 获取任务上下文流程变量。
	 * 
	 * @param request
	 * @return Map&lt;String,Object>
	 */
	private Map<String, Object> getTaskVars(String taskId) {
		Map<String, Object> params = new HashMap<String, Object>();
		if (StringUtil.isEmpty(taskId))
			return params;
		IBpmTask bpmTask = bpmTaskService.getByTaskId(taskId);

		List<IBpmVariableDefine> list = bpmDefineService.getVariableDefs(bpmTask.getProcDefId(), bpmTask.getNodeId());
		if (BeanUtils.isEmpty(list))
			return params;
		for (IBpmVariableDefine varDef : list) {
			params.put(varDef.getKey(),
					BpmVariableDefine.getValue(varDef.getDataType(), varDef.getDefaultVal().toString()));
		}
		return params;
	}

	/**
	 * 获取发起的cmd格式数据。
	 * 
	 * @param request
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private IbpsProcInstCmd getStartCmd(String defId, String destination, String fstNodeUserJs, String secNodeUserJs,
			String data, String proInstId, String procVars) {

		IBpmDefine bpmDefinition = bpmDefineService.getBpmDefinitionByDefId(defId);
		String defKey = bpmDefinition.getDefKey();

		IbpsProcInstCmd cmd = new IbpsProcInstCmd();
		cmd.setFlowKey(defKey);
		// 主键获取
		JSONObject rs = JSONObject.fromObject(data);
		if (rs.containsKey("id") && StringUtil.isNotEmpty(rs.getString("id"))) {
			cmd.setBusinessKey(rs.getString("id"));
		} else {
			cmd.setBusinessKey(UniqueIdUtil.getId());
		}
		cmd.setDestination(destination);
		cmd.setBusData(data);
		if (StringUtil.isNotEmpty(data)) {
			cmd.setDataMode(DataSaveMode.TABLE);
		}

		// 指定发起人
		Map<String, List<BpmIdentity>> fstNodeUsers = BpmIdentityUtil.getBpmIdentity(fstNodeUserJs);
		if (BeanUtils.isNotEmpty(fstNodeUsers)) {
			cmd.addTransitVars(BpmConstants.BPM_NODE_USERS, fstNodeUsers);
		}
		// 指定跳过第一节点执行人
		Map<String, List<BpmIdentity>> secNodeUsers = BpmIdentityUtil.getBpmIdentity(secNodeUserJs);
		if (BeanUtils.isNotEmpty(secNodeUsers)) {
			cmd.addTransitVars(BpmConstants.SEC_BPM_NODE_USERS, secNodeUsers);
		}

		Map<String, Object> params = getProcessStartVars(defId);
		// 动态变量设置
		JSONObject procVarsJS = JSONObject.fromObject(StringUtil.isNotEmpty(procVars) ? procVars : "{}");
		Iterator<String> keys = procVarsJS.keys();
		while (keys.hasNext()) {
			String key = keys.next().toString();
			String value = procVarsJS.get(key).toString();
			params.put(key, value);
		}
		cmd.setVariables(params);

		if (StringUtil.isNotEmpty(proInstId)) {
			cmd.setInstId(proInstId);
		}
		// 当前用户
		if (StringUtil.isNotEmpty(fstNodeUserJs)) {
			JSONObject curUser = JSONObject.fromObject(JSONArray.fromObject(
					JSONObject.fromObject(JSONArray.fromObject(fstNodeUserJs).get(0).toString()).getString("executors"))
					.get(0).toString());
			cmd.setCurUser(curUser.getString("id"));
			cmd.setCurUserName(curUser.getString("name"));
		} else {
			User curUser = ContextUtil.getCurrentUser();
			cmd.setCurUser(curUser.getUserId());
			cmd.setTenantId(ContextUtil.getCurrentTenantId());
			cmd.setCurUserName(curUser.getFullname());
		}

		return cmd;
	}

	private Map<String, Object> getProcessStartVars(String defId) {
		Map<String, Object> params = new HashMap<String, Object>();
		List<IBpmVariableDefine> list = bpmDefineService.getVariableDefs(defId);
		if (BeanUtils.isEmpty(list))
			return params;
		for (IBpmVariableDefine varDef : list) {
			params.put(varDef.getKey(),
					BpmVariableDefine.getValue(varDef.getDataType(), varDef.getDefaultVal().toString()));
		}
		return params;
	}

	/**
	 * 处理选择路径跳转的分支出口
	 *
	 * @param outgoingNodes
	 * @return
	 */
	private List<IBpmNodeDefine> handlerSelectOutgoingNodes(List<IBpmNodeDefine> outgoingNodes) {
		int size = outgoingNodes.size();
		List<IBpmNodeDefine> returnList = new ArrayList<IBpmNodeDefine>();
		if (size == 1) {
			IBpmNodeDefine bpmNodeDef = outgoingNodes.get(0);
			NodeType nodeType = bpmNodeDef.getType();
			// 网关节点
			if (NodeType.EXCLUSIVEGATEWAY.equals(nodeType) || NodeType.INCLUSIVEGATEWAY.equals(nodeType)
					|| NodeType.PARALLELGATEWAY.equals(nodeType)) {
				returnList = bpmNodeDef.getOutgoingNodeList();
			}
		}
		if (BeanUtils.isEmpty(returnList)) {
			return outgoingNodes;
		} else {
			return returnList;
		}
	}

	@ApiOperation(value = "下一节点类型", notes = "下一节点类型")
	@RequestMapping(value = "/getNextNodeType", method = RequestMethod.POST)
	public APIResult<String> getNextNodeType(
			@RequestParam(name = "taskId", required = false) @ApiParam(name = "taskId", value = "流程任务ID", required = false) String taskId,
			@RequestParam(name = "defId", required = false) @ApiParam(name = "defId", value = "流程定义ID", required = false) String defId,
			@RequestParam(name = "curNode", required = false) @ApiParam(name = "curNode", value = "所在节点", required = false) String curNode) {
		APIResult<String> result = new APIResult<>();

		try {
			IBpmTask task = null;
			if (StringUtil.isNotEmpty(taskId)) {
				task = bpmTaskService.getByTaskId(taskId);
				if (task != null) {
					defId = task.getProcDefId(); // 流程定义ID
					curNode = task.getNodeId(); // 所在节点
				}
			}

			List<IBpmNodeDefine> nodes = bpmDefineReader.getNode(defId, curNode).getOutgoingNodeList();
			String nodeType = null;
			if (BeanUtils.isNotEmpty(nodes)) {
				nodeType = nodes.get(0).getType().getKey();
			}

			result.setData(nodeType);
			result.setMessage("获取节点类型成功");
		} catch (Exception e) {
			result = getExceptionResult(result, ERROR, "获取节点类型失败", e);
		}
		return result;
	}

	/**
	 * 获取表单详情，用于启动流程
	 * 
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@ApiOperation(value = "获取表单", notes = "获取表单，主要用于启动流程")
	@RequestMapping(value = "/getFormDataForInst", method = RequestMethod.GET)
	public APIResult<Map<String, Object>> getFormDataForInst(
			@RequestParam(name = "defId", required = false) @ApiParam(name = "defId", value = "流程定义ID", required = false) String defId,
			@RequestParam(name = "proInstId", required = false) @ApiParam(name = "proInstId", value = "流程实例ID", required = false) String proInstId) {
		APIResult<Map<String, Object>> result = new APIResult<Map<String, Object>>();
		if (BeanUtils.isEmpty(defId) && BeanUtils.isEmpty(proInstId)) {
			result = getResult(result, FAIL, "参数错误，请进行仔细检查！");
			return result;
		}
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("result", true);
		IDataObject dataObject = null;
		IFormModel formModel = null;
		String permissions = "";
		boolean isStart = StringUtil.isNotEmpty(proInstId) ? false : true;
		try {
			//设置标题
			IBpmDefine define =bpmDefineService.getBpmDefinitionByDefId(defId);
			map.put("title", define.getName());
			IBpmNodeDefine startNode = bpmDefineReader.getStartEvent(defId);
			// 获取节点按钮
			List<Button> buttons = BpmButtonUtil.getButtons(startNode);
			// 获取表单
			formModel = bpmFormService.getByDefId(defId);
			// 表单权限
			if (BeanUtils.isNotEmpty(formModel) && FormCategory.INNER.equals(formModel.getType())) {// 在线表单
				// 获取表单第一个节点
				List<IBpmNodeDefine> firstNode = bpmDefineReader.findStartNode(defId);
				IBpmNodeDefine firstNode0 = BeanUtils.isNotEmpty(firstNode) ? firstNode.get(0) : null;

				// 表单数据
				dataObject = getDataObject(proInstId, defId);
				Map<String, String> rightsMap = new HashMap<String, String>();
				rightsMap.put(FormPermissionVo.FLOW_KEY,
						BeanUtils.isNotEmpty(firstNode0) ? firstNode0.getBpmProcDefine().getProcDefineKey() : null);
				rightsMap.put(FormPermissionVo.NODE_ID,
						BeanUtils.isNotEmpty(firstNode0) ? firstNode0.getNodeId() : null);

				permissions = formRightsService.getPermission(new FormPermissionVo(RightsScope.NODE,
						ContextUtil.getCurrentUserId(), formModel.getKey(), rightsMap));
			}

			map.put("isStart", isStart);
			// 按钮
			map.put("buttons", buttons);
			// 表单
			map.put("formModel", formModel);
			// bo数据
			map.put("boData", BeanUtils.isNotEmpty(dataObject) ? dataObject.getData() : null);
			// 表单
			map.put("permissions", permissions);

			Map<String, Object> attributes = Maps.newHashMap();
			map.put("attributes", attributes);

			// 取流程定义第一个节点id
			IBpmDefineReader defReader = AppUtil.getBean(IBpmDefineReader.class);
			List<IBpmNodeDefine> nodes = defReader.findStartNode(defId);
			String firstNodeId = nodes.get(0).getNodeId();
			map.put("firstNodeId", firstNodeId);

			result.setMessage("成功获取数据！");
		} catch (Exception e) {
			result = getExceptionResult(result, ERROR, "获取数据失败！", e);
		}
		result.setData(map);
		return result;
	}

	private IDataObject getDataObject(String proInstId, String defId) {
		IDataObject dataObject = null;
		if (StringUtil.isNotEmpty(proInstId)) {
			dataObject = bpmBoService.getDataByInst(bpmInstService.getProcInst(proInstId));
		} else {
			// 处理bo数据
			dataObject = bpmBoService.getDataByDefId(defId);
		}
		return dataObject;
	}

	@ApiOperation(value = "获取流程定义", notes = "获取表单")
	@RequestMapping(value = "/defList", method = RequestMethod.POST)
	public APIResult<APIPageList<BpmDefinePo>> defList(
			@ApiParam(name = "request", value = "传入查询请求json字符串", required = true) @RequestBody(required = true) APIRequest request) {
		APIResult<APIPageList<BpmDefinePo>> result = new APIResult<>();

		QueryFilter queryFilter = getQuerFilter(request);

		try {
			// 获取最新主版本的信息列表
			queryFilter.addFilter("is_main_", "Y", QueryOP.EQUAL);
			List<FieldSort> fieldSorts = queryFilter.getFieldSortList();
//			if (StringUtil.isNotEmpty(typeId)) {
//				queryFilter.addFilter("type_id_", typeId, QueryOP.EQUAL);
//			}
			if (BeanUtils.isEmpty(fieldSorts)) {
				fieldSorts = new ArrayList<FieldSort>();
				fieldSorts.add(new DefaultFieldSort("update_time_", Direction.fromString("desc")));
				queryFilter.setFieldSortList(fieldSorts);
			}
			boolean isSuper = ContextUtil.isSuper();
			String listData = bpmDefineService.query(queryFilter, ContextUtil.getCurrentUserId(), isSuper);
			PageList<BpmDefinePo> bpmDefinePoList = null;
			if (JacksonUtil.isJsonObject(listData)) {
				List<BpmDefinePo> list = BpmDefinePo.fromJsonArrayString(JacksonUtil.getString(listData, "data"));
				PageResult pageResult = PageResult.fromJson(JacksonUtil.getString(listData, "pageResult"));
				bpmDefinePoList = new PageList<BpmDefinePo>(list, pageResult);
				APIPageList<BpmDefinePo> pageList = getAPIPageList(bpmDefinePoList);
				result.setData(pageList);
			} else if (BeanUtils.isEmpty(listData)) {
				result.setData(null);
			} else {
				result.setState(FAIL);
			}
		} catch (Exception e) {
			result = getExceptionResult(result, ERROR, "获取流程定义列表失败", e);
		}

		return result;
	}

	@ApiOperation(value = "锁定任务", notes = "锁定任务")
	@RequestMapping(value = "/lock", method = RequestMethod.GET)
	public APIResult<String> lock(
			@ApiParam(name = "taskId", value = "任务ID", required = false) @RequestParam(name = "taskId", required = false) String taskId) {
		APIResult<String> result = new APIResult<>();
		if (StringUtil.isEmpty(taskId)) {
			result = getResult(result, FAIL, "锁定任务失败，任务ID为空！");
			return result;
		}

		try {
			bpmTaskManagerService.lock(ContextUtil.getCurrentUserId(), taskId);

			result.setMessage("锁定任务成功");
		} catch (Exception e) {
			result = getExceptionResult(result, ERROR, "锁定任务失败", e);
		}
		return result;
	}

	@ApiOperation(value = "解锁任务", notes = "解锁任务")
	@RequestMapping(value = "/unlock", method = RequestMethod.GET)
	public APIResult<String> unlock(
			@ApiParam(name = "taskId", value = "任务ID", required = false) @RequestParam(name = "taskId", required = false) String taskId) {
		APIResult<String> result = new APIResult<>();
		if (StringUtil.isEmpty(taskId)) {
			result = getResult(result, FAIL, "锁定任务失败，任务ID为空！");
			return result;
		}

		try {
			bpmTaskManagerService.unlock(ContextUtil.getCurrentUserId(), ContextUtil.isSuper(), taskId);

			result.setMessage("解锁任务成功");
		} catch (Exception e) {
			result = getExceptionResult(result, ERROR, "解锁任务失败", e);
		}
		return result;
	}

	@ApiOperation(value = "挂起流程实例", notes = "挂起流程实例")
	@RequestMapping(value = "/suspendProcess", method = RequestMethod.GET)
	public APIResult<String> suspendProcess(
			@ApiParam(name = "taskId", value = "任务ID", required = false) @RequestParam(name = "taskId", required = false) String taskId) {
		APIResult<String> result = new APIResult<>();
		if (StringUtil.isEmpty(taskId)) {
			result = getResult(result, FAIL, "流程实例挂起失败，任务ID为空！");
			return result;
		}

		try {
			bpmTaskManagerService.suspendProcess(taskId);

			result.setMessage("流程实例挂起成功");
		} catch (Exception e) {
			result = getExceptionResult(result, ERROR, "流程实例挂起失败", e);
		}
		return result;
	}

	@ApiOperation(value = "恢复流程实例", notes = "恢复流程实例")
	@RequestMapping(value = "/recoverProcess", method = RequestMethod.GET)
	public APIResult<String> recoverProcess(
			@ApiParam(name = "taskId", value = "任务ID", required = false) @RequestParam(name = "taskId", required = false) String taskId) {
		APIResult<String> result = new APIResult<>();
		if (StringUtil.isEmpty(taskId)) {
			result = getResult(result, FAIL, "流程实例恢复失败，任务ID为空！");
			return result;
		}

		try {
			bpmTaskManagerService.recoverProcess(taskId);

			result.setMessage("流程实例恢复成功");
		} catch (Exception e) {
			result = getExceptionResult(result, ERROR, "流程实例恢复失败", e);
		}
		return result;
	}
	
	@ApiOperation(value = "批量处理任务", notes = "同意")
	@RequestMapping(value = "completeBatch", method = RequestMethod.POST)
	public APIResult<String> completeBatch(
			@ApiParam(name = "taskId", value = "任务ID", required = false) @RequestParam(name = "taskId", required = false) String taskId,
			@ApiParam(name = "actionName", value = "操作", required = false) @RequestParam(name = "actionName", required = false) String actionName,
			@ApiParam(name = "opinion", value = "意见", required = false) @RequestParam(name = "opinion", required = false) String opinion) {
		APIResult<String> result = new APIResult<>();
		IbpsTaskFinishCmd cmd = getCmdFromRequestForBatch(taskId, actionName, opinion);
		try {
			
			bpmTaskActionService.finishTasks(cmd);
			result.setMessage("任务办理成功");
		} catch (Exception e) {
			result = getExceptionResult(result, ERROR, "任务办理失败", e);
		}
		return result;
	}
	
	/**
	 * 从上下文请求获取包装后的cmd对象。
	 * 
	 * @param request
	 * @return DefaultTaskFinishCmd
	 */
	private IbpsTaskFinishCmd getCmdFromRequestForBatch(String taskIds, String actionName, String opinion) {
		String busData = null;
		String nodeUsers = null;
		
		String directHandlerSign = null;
		String backHandMode = null;
		
		String jumpType = "common";
		String destination = "";
		if(StringUtil.isNotEmpty(nodeUsers)){
			JSONArray nodeUserArr = JSONArray.fromObject(nodeUsers);
			if(JsonUtil.isNotEmpty(nodeUserArr)){
				jumpType = JsonUtil.getString(nodeUserArr.getJSONObject(0), "jumpType");
				destination = JsonUtil.getString(nodeUserArr.getJSONObject(0), "nodeId");
			}
		}
		
		IbpsTaskFinishCmd cmd = new IbpsTaskFinishCmd();
		
		User curUser = ContextUtil.getCurrentUser();
		cmd.setOptIp(RequestUtil.getIpAddr(request));
		cmd.setCurUser(curUser.getUserId());
		cmd.setCurUserName(curUser.getFullname());
		cmd.setSuperUser(curUser.isSuper());
		
		cmd.setTaskIds(taskIds);
		cmd.setActionName(actionName);// 处理动作
		
		// 指定路径、自由跳转
		if ("select".equals(jumpType) || "free".equals(jumpType)) {
			if (StringUtil.isNotEmpty(destination)) {
				cmd.setDestination(destination);
			}
		}
		
		// 指定执行人
		if (BeanUtils.isNotEmpty(nodeUsers)) {
			Map<String, List<BpmIdentity>> specUserMap = BpmIdentityUtil.getBpmIdentity(nodeUsers);
			cmd.addTransitVars(BpmConstants.BPM_NODE_USERS, specUserMap);
		}
		
		// 设置流程驳回时跳转模式
		cmd.addTransitVars(BpmConstants.BACK_HAND_MODE, backHandMode);
		if (ActionType.REJECT.getKey().equals(actionName)) {
			// 驳回到指定节点
			destination = null;
			if (StringUtil.isNotEmpty(destination)) {
				cmd.setDestination(destination);
			}
		}
		
		// 会签任务的直接处理
		if ("true".equals(directHandlerSign)) {
			cmd.addTransitVars(BpmConstants.SIGN_DIRECT, "1");
		}
		
		// 设置表单意见
		cmd.setApprovalOpinion(opinion);
		handOpinion(busData, cmd);
		
		return cmd;
	}
	
	/**
	 * 流程实例-批量挂起
	 * 
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@ApiOperation(value = "批量挂起流程实例", notes = "批量挂起流程实例")
	@RequestMapping(value = "batchSuspendProcess", method=RequestMethod.POST)
	public APIResult<String> batchSuspendProcess(
			@ApiParam(name = "taskIds", value = "任务IDs", required = true) @RequestParam(name = "taskIds", required = true) String taskIds) {
		APIResult<String> result = new APIResult<>();
		if(StringUtil.isEmpty(taskIds)){
			return getResult(result, FAIL, "请输入正确参数!");
		}
		
		try{
			bpmInstService.batchSuspendProcInst(taskIds);
			result.setMessage("流程实例挂起成功!");
		}catch (Exception e){
			result = getExceptionResult(result, ERROR, "流程实例挂起失败!", e);
		}
		return result;
	}
	
	/**
	 * 流程实例-批量恢复
	 * 
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@ApiOperation(value = "批量恢复流程实例", notes = "批量恢复流程实例")
	@RequestMapping(value = "batchRecoverProcess", method=RequestMethod.POST)
	public APIResult<String> batchRecoverProcess(
			@ApiParam(name = "taskIds", value = "任务IDs", required = true) @RequestParam(name = "taskIds", required = true) String taskIds) {
		APIResult<String> result = new APIResult<>();
		if(StringUtil.isEmpty(taskIds)){
			return getResult(result, FAIL, "请输入正确参数!");
		}
		
		try{
			bpmInstService.batchRecoverProcInst(taskIds);
			result.setMessage("流程实例恢复成功!");
		}catch (Exception e){
			result = getExceptionResult(result, ERROR, "流程实例恢复失败!", e);
		}
		return result;
	}
	
	
	/**
	 * 获取流程实例中指定节点的审批意见
	 * 
	 * @return
	 * @throws Exception
	 */
	@ApiOperation(value = " 获取流程实例中指定节点的审批意见", notes = " 获取流程实例中指定节点的审批意见")
	@RequestMapping(value = "getNodeApproval", method=RequestMethod.GET)
	public APIResult<Map<String, Object>> getNodeApproval(
			@RequestParam(name = "bpmnInstId", required = false)
			@ApiParam(name = "bpmnInstId", value = "bpmnInstId", required = false) String bpmnInstId,
			@RequestParam(name = "taskId", required = false)
			@ApiParam(name = "taskId", value = "taskId", required = false) String taskId,
			@RequestParam(name = "nodeId", required = true) 
			@ApiParam(name = "nodeId", value = "nodeId", required = true) String nodeId
			) throws Exception {
		APIResult<Map<String, Object>> result = new APIResult<Map<String, Object>>();
		try{
			if(BeanUtils.isEmpty(bpmnInstId) &&  BeanUtils.isNotEmpty(taskId)){
				IBpmTask task = bpmTaskService.getByTaskId(taskId);
				bpmnInstId = task.getProcInstId();
			}
			Map<String, Object> data = bpmApprovalService.setApprovalerName(bpmApprovalService.getNodeApprovalMap(bpmnInstId, nodeId));

			int bpmNodeUserShowCount = Integer.valueOf(AppUtil.getProperty("bpm.node.user.show.count", "5"));
			data.put("bpmNodeUserShowCount", bpmNodeUserShowCount);
			result.setData(data);
		}catch (Exception e){
			result = getExceptionResult(result, ERROR, "获取流程实例中指定节点的审批意见失败!", e);
		}
		return result;
	}
	
	/**
	 * 会签任务-补签
	 * 
	 * @return
	 * @throws Exception
	 */
	@ApiOperation(value = "补签", notes = "补签")
	@RequestMapping(value = "doAddSignTask", method=RequestMethod.POST)
	public APIResult<Map<String, Object>> doAddSignTask(
			@RequestParam(name = "taskId", required = true)
			@ApiParam(name = "taskId", value = "taskId", required = true) String taskId,
			@RequestParam(name = "addSignTaskUserId", required = true)
			@ApiParam(name = "addSignTaskUserId", value = "addSignTaskUserId", required = true) String addSignTaskUserId,
			@RequestParam(name = "messageType", required = true) 
			@ApiParam(name = "messageType", value = "messageType", required = true) String messageType,
			@RequestParam(name = "addReason", required = false)
			@ApiParam(name = "addReason", value = "addReason", required = false) String addReason
			) throws Exception {
		APIResult<Map<String, Object>> result = new APIResult<Map<String, Object>>();
		try{
			User curUser = ContextUtil.getCurrentUser();
			Boolean isSuper = ContextUtil.isSuper();
			ResultMessage addSignTask = signService.addSignTask(curUser.getUserId(), isSuper, taskId, addSignTaskUserId.split(","), messageType.split(","), addReason);
			
			if (addSignTask.getResult() == ResultMessage.SUCCESS) {
				result.setMessage("补签成功");
			} else {
				result = getResult(result, FAIL, "补签失败," + addSignTask.getMessage());
			}
		}catch (Exception e){
			result = getExceptionResult(result, ERROR, "补签失败!", e);
		}
		return result;
	}

}
